use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Mutex;

use lazy_static::lazy_static;

use crate::vm_thread::{VMFrame, VMThread};

lazy_static! {
    static ref NATIVE_METHOD_REGISTER: Mutex<NativeMethodRegister> = {
        Mutex::new(NativeMethodRegister { register: RefCell::new(HashMap::new()) })
    };
}

pub struct NativeMethodRegister {
    register: RefCell<HashMap<String, fn(frame: Rc<RefCell<VMFrame>>, thread: &VMThread)>>,
}

impl NativeMethodRegister {
    pub fn register(class_name: &String, method_name: &String, method_descriptor: &String, func: fn(frame: Rc<RefCell<VMFrame>>, thread: &VMThread)) {
        let key = format!("{}#{}#{}", class_name, method_name, method_descriptor);
        let lock = NATIVE_METHOD_REGISTER.lock();
        let native_method_register = lock.unwrap();
        native_method_register.register.borrow_mut().insert(key, func);
    }

    pub fn find_method(class_name: &String, method_name: &String, method_descriptor: &String)
                       -> Result<fn(frame: Rc<RefCell<VMFrame>>, thread: &VMThread), String> {
        let key = format!("{}#{}#{}", class_name, method_name, method_descriptor);
        let lock = NATIVE_METHOD_REGISTER.lock();
        let native_method_register = lock.unwrap();
        let ro_register = native_method_register.register.borrow();
        let result = ro_register.get(&key);
        if result.is_none() {
            return Err(format!("native方法查询失败:{}", key));
        }
        return Ok(*result.unwrap());
    }
}